package com.vert.utils;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @Classname JarScanUtils
 * @Description TODO
 * @Date 2022/6/1 16:00
 * @Created by XiongXiong
 * @Author: X.I.O
 */
public class JarScanUtils {

  public static void clear(){
      classSet.clear();
  }

  private static Set<Class<?>>  classSet=new HashSet<>();

  public static Set<Class<?>> loadAllJarFromAbsolute(String directoryPath) throws
       NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {
    System.out.println(classSet.size());
      File directory = new File(directoryPath);
      // 判断是否为文件夹，如果是文件,直接用单个jar解析的方法去解析
      if (!directory.isDirectory()) {
        // 添加jar扫描路径
        addUrl(directory);
        return loadJarFromAbsolute(directoryPath);
      }
    // 如果是文件夹，则需要循环加载当前文件夹下面的所有jar
    //Map<String, Object> clazzMap = new HashMap<>(16);
    File[] jars = directory.listFiles();
    if (jars != null && jars.length > 0) {
      List<String> jarPath = new LinkedList<>();
      for (File file : jars) {
        String fPath = file.getPath();
        // 只加载jar
        if (fPath.endsWith(".jar")) {
          addUrl(file);
          jarPath.add(fPath);
        }
      }

    }
    return classSet;
  }

  private static Set<Class<?>> loadJarFromAbsolute(String path) throws IOException {
    System.out.println(path+"path==>");
      JarFile jar = new JarFile(path);
      Enumeration<JarEntry> entryEnumeration = jar.entries();
      Map<String, Object> clazzMap = new HashMap<>(32);
      while (entryEnumeration.hasMoreElements()) {
        JarEntry entry = entryEnumeration.nextElement();

        // 先获取类的名称，符合条件之后再做处理，避免处理不符合条件的类
        String clazzName = entry.getName();

        if (clazzName.endsWith(".class")  ) {
          // 去掉文件名的后缀
          clazzName = clazzName.substring(0, clazzName.length() - 6);
          // 替换分隔符
          clazzName = clazzName.replace("/", ".");
          // 加载类,如果失败直接跳过

          URLClassLoader classLoader = LoadJarUtils.getUrlClassLoader();
          //cl.loadClass()
          try {
            Class<?> clazz=classLoader.loadClass(clazzName);
           //   Class<?> clazz = Class.forName(clazzName);
              classSet.add(clazz);
          } catch (Throwable e) {
            // 这里可能出现有些类是依赖不全的，直接跳过，不做处理，也没法做处理
          }
        }
      }
      return classSet;
  }

  private static void addUrl(File jarPath) throws NoSuchMethodException, InvocationTargetException,
        IllegalAccessException, MalformedURLException {

       LoadJarUtils.reloadJar(jarPath.getPath());
       URLClassLoader classLoader = LoadJarUtils.getUrlClassLoader();
        //URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
        Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
        if (!method.isAccessible()) {
            method.setAccessible(true);
        }
        URL url = jarPath.toURI().toURL();

        // 把当前jar的路径加入到类加载器需要扫描的路径
        method.invoke(classLoader, url);
  }

}
